import { _decorator, Component, Prefab, instantiate, Node, Vec3, view, math, UITransform, v3, isValid, NodePool } from 'cc';
import { BlockType, GameEventType } from '../Event/EnumDefine';
import { EventManager } from '../Event/EventManager';
import { Block } from './Block';
import { DataConfig } from '../Config/DataConfig';
import { CustomBlock } from './CustomBlock';
import Common from '../Config/Common';
import SHtml from '../SHtml/SHtml';
const { ccclass, property } = _decorator;
/**
 * 数字块生成管理器
 */
@ccclass('HexagonManager')
export class HexagonManager extends Component {

    @property(Prefab)
    hexagonPrefab: Prefab = null;

    @property
    rowCount: number = 6; // 每排最多8个六边形

    @property
    blockWidth: number = 117; // 数字块宽度

    @property
    blockHeight: number = 119; // 数字块高度

    @property(Node)
    randomShapeNode: Node; // 初始随机形状节点数据

    @property(Node)
    zeroShapeNode: Node; // 0形状节点数据

    @property(Node)
    sShapeNode: Node; // s形状节点数据

    private initSpeed: number = 100; // 移动速度
    private speedDis: number = 0;
    private speed: number = 100; // 移动速度
    private rotationSpeed: number = 30; // 旋转速度（度/秒）
    private rowRandomCount: number = 20;  //随机生成方块时的累计索引

    private customNodes: Node[] = [];
    private customNodesHeight: number = 0;

    private rows: Node[] = [];
    private lastRow: Node;  //上一次最近新生成的行节点
    private isRandomBlockStart = false; //随机生成是否开始

    private blockParentPool: NodePool = new NodePool();

    onLoad(): void {
        EventManager.instance.registerEvent(GameEventType.Game_Start, this.onGameStart, this);
        EventManager.instance.registerEvent(GameEventType.Stop_Create_Block, this.onStopCreateBlock, this);
        EventManager.instance.registerEvent(GameEventType.Change_Roll_Speed, (speed: number) => {
            this.speed = speed
        }, this);
    }

    protected start(): void {
        this.initPool();
    }

    initPool() {
        this.blockParentPool.clear();
        for (let i = 0; i < 50; i++) {
            const blocksNode = instantiate(this.hexagonPrefab);
            this.blockParentPool.put(blocksNode);
        }
    }

    getBlockParentNode() {
        if (this.blockParentPool.size() === 0) {
            const blocksNode = instantiate(this.hexagonPrefab);
            this.blockParentPool.put(blocksNode);
        }
        return this.blockParentPool.get();
    }

    removeBlockParentNode(blocksNode: Node) {
        blocksNode.removeFromParent();
        this.blockParentPool.put(blocksNode);
    }

    onGameStart() {
        SHtml.instance.pGameStart();
        // 随机自定义数字块布局初始化
        this.traverseChildren(this.randomShapeNode);
        // 0形状自定义数字块布局初始化
        this.scheduleOnce(() => {
            this.traverseChildren(this.zeroShapeNode);
        }, 0.1)
        // S形状自定义数字块布局初始化
        this.scheduleOnce(() => {
            this.traverseChildren(this.sShapeNode);
        }, 0.2)
        this.initSpeed = this.speed;
        this.speed = this.initSpeed * 8;
    }

    onStopCreateBlock() {
        this.isRandomBlockStart = false;
    }
    // 遍历所有子节点
    traverseChildren(node: Node) {
        const screenSize = Common.instance.getScreenSize();
        let nodeHight = node.getComponent(UITransform).height;
        node.setPosition(v3(0, screenSize.height / 2 + this.customNodesHeight + nodeHight / 2))
        this.customNodesHeight += nodeHight;
        this.customNodes.push(node);
        let is_s_shape = node.name == 'SShapeNode';
        for (let child of node.children) {
            // 获取 CustomBlock 组件
            const customBlock = child.getComponent(CustomBlock);
            if (customBlock) {
                // 获取 customBlockType 和 customBlockNum 属性
                const customBlockType = customBlock.customBlockType;
                const customBlockNum = is_s_shape ? Math.floor(customBlock.customBlockNum * 0.7) : customBlock.customBlockNum;
                this.createBlock(customBlockType, customBlockNum, node, child.position)
            }
        }
    }

    /** 更新字节点的旋转角度为正向，避免数字角度不正 */
    updateChildrenAngle(node: Node, angle: number) {
        // 获取所有子节点
        const children = node.children;
        for (let i = 0; i < children.length; i++) {
            children[i].angle = angle;
        }
    }

    // 根据 Y 坐标更新子节点的渲染顺序
    updateChildrenRenderOrder(node: Node) {
        // 获取所有子节点
        const children = node.children;

        // 按 世界坐标Y 坐标排序（Y 越小，层级越高）
        children.sort((a, b) => b.worldPosition.y - a.worldPosition.y);
        // 设置渲染顺序
        for (let i = 0; i < children.length; i++) {
            children[i].setSiblingIndex(i);
        }
    }

    update(dt: number) {
        if (DataConfig.isGameStop) {
            return;
        }
        if (this.speed > this.initSpeed) {
            this.speedDis += 0.75;
            this.speed -= this.speedDis;
        }
        else {
            this.speed = this.initSpeed;
        }
        const screenSize = Common.instance.getScreenSize();
        // 随机创建新数字块
        if (this.isRandomBlockStart) {
            if (!this.lastRow) {
                //首次创建
                this.generateRow();
            } else if ((this.lastRow.position.y + this.blockHeight / 2) <= screenSize.height / 2) {
                // 上一次创建的行数字块已经完全展示到屏幕内，就新创建一个
                this.generateRow();
            }
        }

        // 自定义布局节点位置更新
        this.customNodes.forEach(rootNode => {
            if (rootNode.name == 'SShapeNode') {
                // 计算旋转角度
                rootNode.angle += this.rotationSpeed * dt;
                let angleBlock = -rootNode.angle;
                rootNode.children.forEach((block) => {
                    block.angle = angleBlock;
                });
            }
            // 更新层级
            this.updateChildrenRenderOrder(rootNode);
            // 位置更新
            const nodeHight = rootNode.getComponent(UITransform).height;
            rootNode.position = rootNode.position.clone().subtract(new Vec3(0, this.speed * dt, 0));
            if (rootNode.position.y < (-screenSize.height / 2 - 100)) {
                rootNode.destroy();
                this.customNodes.splice(this.customNodes.indexOf(rootNode), 1);
                // 剩余最后一个S型状在屏幕内时，开始随机数字块
                if (this.customNodes.length == 1) {
                    this.onRandomBlockStart()
                }
            }
        });

        // 随机布局节点位置更新
        this.rows.forEach(row => {
            row.position = row.position.clone().subtract(new Vec3(0, this.speed * dt, 0));
            if (row.position.y < (-screenSize.height / 2 - this.blockHeight)) {
                row.children.forEach((blockParentNode: Node)=>{
                    this.removeBlockParentNode(blockParentNode);
                });
                this.rows.splice(this.rows.indexOf(row), 1);
            }
        });

        SHtml.instance.pStuck(dt);
    }

    /** 随机生成数字块开始 */
    onRandomBlockStart() {
        this.isRandomBlockStart = true;
    }

    generateRow() {
        const screenSize = Common.instance.getScreenSize();
        const row = new Node();
        const hexagonCount = Math.floor(Math.random() * this.rowCount) + 1; // 随机生成1到8个六边形
        this.rowRandomCount++;
        for (let i = 0; i < hexagonCount; i++) {
            const blockTypeList = DataConfig.blockTypeList;
            const typeIndex = math.randomRangeInt(0, blockTypeList.length); // 随机生成一个方块颜色类型
            const blockType = blockTypeList[typeIndex];
            const blockCount = math.randomRangeInt(10, this.rowRandomCount + 1); // 随机生成 1 到 10 的整数
            const pos = v3(i * this.blockWidth, 0, 0);
            this.createBlock(blockType, blockCount, row, pos);
        }

        // 错开排列
        // row.setPosition(-(hexagonCount * 50 - 50), this.node.position.y, 0);
        const halfWidth = this.blockWidth / 2;
        row.setPosition(-(hexagonCount * halfWidth - halfWidth), screenSize.height / 2 + this.blockHeight / 2, 0);
        this.lastRow = row;

        this.node.addChild(row);
        row.setSiblingIndex(0);
        this.rows.push(row);
    }

    createBlock(blockType: BlockType, blockCount: number, parentNode: Node, pos: Vec3) {
        const blockParentNode = this.getBlockParentNode();
        parentNode.addChild(blockParentNode);
        blockParentNode.setPosition(pos);
        const com = blockParentNode.getComponent(Block);
        com.startGenerateBlocks(blockType, blockCount);
    }
}
